package com.niiwoo.civet.account.service.local.openAccount2.service;

import com.alibaba.fastjson.JSON;
import com.niiwoo.civet.account.constant.AccountRegisterErrorCode;
import com.niiwoo.civet.account.dao.entity.OpenAccountRecord;
import com.niiwoo.civet.account.enums.OpenAccountRecordStatusEnum;
import com.niiwoo.civet.account.enums.OpenAccountWayEnum;
import com.niiwoo.civet.account.service.local.openAccount2.dto.AccountInfo;
import com.niiwoo.civet.account.service.local.openAccount2.dto.CreateRequest;
import com.niiwoo.civet.account.service.local.openAccount2.dto.EnterpriseRegisterOrder;
import com.niiwoo.civet.account.service.local.openAccount2.dto.EnterpriseRegisterUpdateRequest;
import com.niiwoo.civet.account.service.local.openAccount2.dto.UpdateRequest;
import com.niiwoo.civet.account.service.local.openAccount2.dto.UpdateResponse;
import com.niiwoo.civet.account.service.local.openAccount2.type.MockEnterpriseRegisterTypeable;
import com.niiwoo.tripod.base.component.PrivacyMasks;
import com.niiwoo.tripod.base.exception.VerifyFailedException;
import com.niiwoo.tripod.lanmao.component.LanMaoDirectService;
import com.niiwoo.tripod.lanmao.component.LanMaoSequence;
import com.niiwoo.tripod.lanmao.request.QueryUserInformationRequest;
import com.niiwoo.tripod.lanmao.response.LanMaoGatewayDTO;
import com.niiwoo.tripod.lanmao.response.QueryUserInformationResponse;
import com.niiwoo.tripod.provider.exception.BizException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Component
public class EnterpriseOpenAccountService extends AbstractOpenAccountService<EnterpriseRegisterOrder> implements MockEnterpriseRegisterTypeable {

    @Autowired
    PrivacyMasks privacyMasks;

    @Autowired
    LanMaoDirectService lanMaoDirectService;

    @Autowired
    LanMaoSequence lanMaoSequence;

    /**
     * 无订单/记录，直接创建请求参数
     * @param request
     * @return
     */
    @Override
    public LanMaoGatewayDTO create(CreateRequest request) {
        return openAccountLanMaoHandler.get(this.getType()).generateLanMaoGatewayDTO(request, null);
    }

    @Override
    protected void innerCreateParamValid(CreateRequest request) {
        throw new UnsupportedOperationException("不支持的操作");
    }

    @Override
    protected void innerCreateRecordValid(CreateRequest request, List<OpenAccountRecord> recordList) {
        throw new UnsupportedOperationException("不支持的操作");
    }

    /**
     * 仅适用于企业激活回调处理 (企业注册无订单/记录)
     * @param request
     * @return
     */
    @Transactional(isolation = Isolation.READ_COMMITTED)
    @Override
    public UpdateResponse update(UpdateRequest request) {
        log.info("企业激活更新###请求, data={}", JSON.toJSONString(request));
        // 开户记录是否存在
        OpenAccountRecord record = openAccountRecordMapperExt.selectByAccountNo(request.getAccountNo());
        if (record == null) {
            throw new BizException(AccountRegisterErrorCode.ACCOUNT_REGISTER_RECORD_NOT_EXISTS);
        }
        OpenAccountWayEnum openAccountWay = OpenAccountWayEnum.of(record.getOpenAccountWay());
        // 是否激活记录
        if (openAccountWay != OpenAccountWayEnum.ENTERPRISE_ACTIVATE) {
            throw new BizException(AccountRegisterErrorCode.ACCOUNT_REGISTER_RECORD_NOT_EXISTS);
        }
        // 开户是否成功
        if (OpenAccountRecordStatusEnum.except(record.getStatus(), OpenAccountRecordStatusEnum.SUCCESS)) {
            return this.getUpdateResponse(OpenAccountRecordStatusEnum.SUCCESS);
        }
        // 查询懒猫账户激活状态, 账户未激活， 不处理回调
        if (!this.queryLanMaoAccountStatus(record.getAccountNo()).getIsImportUserActivate()) {
            return this.getUpdateResponse(OpenAccountRecordStatusEnum.FAILURE);
        }
        // 开户状态
        OpenAccountRecordStatusEnum recordStatus = super.judgeRecordStatusByAuditStatus(request);
        // 更新开户记录
        OpenAccountRecord updateRecord = new OpenAccountRecord();
        updateRecord.setId(record.getId());
        updateRecord.setStatus(recordStatus.getValue());
        updateRecord.setSuccessTime(recordStatus == OpenAccountRecordStatusEnum.SUCCESS ? new Date() : null); // 成功时间
        updateRecord.setGroupAccountNo(request.getGroupAccountNo()); // 集团账户编号
        boolean recordUpdateResult = openAccountRecordMapperExt.updateStatusById(updateRecord) > 0;
        log.info("企业激活更新###开户记录更新###data={}, result={}", JSON.toJSONString(updateRecord), recordUpdateResult);
        // 开户方式
        // 审核通过, 修改账户信息
        if (recordStatus == OpenAccountRecordStatusEnum.SUCCESS) {
            AccountInfo accountInfo = this.innerUpdateAccountInfo(record, null, request);
            accountInfo.setIsUpdateBankCard(true);
            boolean accountUpdateResult = accountInfoComposite.update(accountInfo);
            log.info("企业激活更新###账户信息更新###data={}, result={}", JSON.toJSONString(accountInfo), accountUpdateResult);
        }
        // 返回响应
        log.info("企业激活更新###结果, status={}", recordStatus);
        return super.getUpdateResponse(recordStatus);
    }

    @Override
    protected AccountInfo innerUpdateAccountInfo(OpenAccountRecord record, EnterpriseRegisterOrder order, UpdateRequest request) {
        EnterpriseRegisterUpdateRequest mockEnterpriseRegisterUpdateRequset = (EnterpriseRegisterUpdateRequest) request;
        AccountInfo accountInfo = new AccountInfo();
        accountInfo.setAccountNo(record.getAccountNo());
        accountInfo.setRole(record.getAccountRole());
        accountInfo.setUserId(record.getUserId());
        accountInfo.setBankCardNo(privacyMasks.encryptPrivacy(mockEnterpriseRegisterUpdateRequset.getBankCardNo()));
        accountInfo.setBankCode(mockEnterpriseRegisterUpdateRequset.getBankCode());
        return accountInfo;
    }

    /**
     * 查询懒猫账户状态
     */
    private QueryUserInformationResponse queryLanMaoAccountStatus(String accountNo) {
        QueryUserInformationRequest request = new QueryUserInformationRequest();
        request.setPlatformUserNo(accountNo);
        request.setRequestNo(lanMaoSequence.getRequestNo());
        QueryUserInformationResponse response;
        try {
            log.info("懒猫接口###查询用户信息接口###request={}", JSON.toJSONString(request));
            response = lanMaoDirectService.queryUserInformation(request).get();
            log.info("懒猫接口###查询用户信息接口###response={}", JSON.toJSONString(response));
            if (!response.isSuccess()) {
                log.error("懒猫接口###查询用户信息接口###请求失败, requestNo={},  errorCode={}, errorMessage={}", request.getRequestNo(), response.getErrorCode(), response.getErrorCode());
                throw new BizException(AccountRegisterErrorCode.LANMAO_QUERY_EXCEPTION);
            }
            return response;
        } catch (ExecutionException e) {
            if (e.getCause() != null && e.getCause() instanceof VerifyFailedException) {
                log.error(String.format("懒猫接口###查询用户信息接口###验签失败, requestNo=%s,  exceptionMessage=%s", request.getRequestNo(), e.getMessage()), e);
                throw new BizException(AccountRegisterErrorCode.LANMAO_QUERY_EXCEPTION);
            } else {
                // 未知异常
                log.error(String.format("懒猫接口###查询用户信息接口###未知异常1， requestNo=%s, exceptionMessage=%s", request.getRequestNo(), e.getMessage()), e);
                throw new BizException(AccountRegisterErrorCode.LANMAO_QUERY_EXCEPTION);
            }
        } catch (Exception e) {
            // 未知异常
            log.error(String.format("懒猫接口###查询用户信息接口###未知异常2， requestNo=%s, exceptionMessage=%s", request.getRequestNo(), e.getMessage()), e);
            throw new BizException(AccountRegisterErrorCode.LANMAO_QUERY_EXCEPTION);
        }
    }

}
